package org.koin.java;

import org.koin.core.Koin;
import org.koin.core.error.ClosedScopeException;
import org.koin.core.error.DefinitionParameterException;
import org.koin.core.error.NoBeanDefFoundException;
import org.koin.core.parameter.ParametersDefinition;
import org.koin.core.qualifier.Qualifier;
import org.koin.mp.KoinPlatformTools;

/**
 * Koin Java Helper - inject/get into Java code
 *
 * @author @fredy-mederos
 * @author Arnaud Giuliani
 */
public class KoinJavaComponent {

    /**
     * Retrieve given dependency lazily
     *
     * @param clazz      - dependency class
     * @param qualifier  - bean canonicalName / optional
     * @param parameters - dependency parameters / optional
     */
    public static <T> T inject(
            Class clazz,
            Qualifier qualifier,
            ParametersDefinition parameters
    ) {
        return get(clazz, qualifier, parameters);
    }

    public static <T> T inject(
            Class clazz,
            Qualifier qualifier
    ) {
        return get(clazz, qualifier, null);
    }

    public static <T> T inject(
            Class clazz
    ) {
        return get(clazz, null, null);
    }

    /**
     * Retrieve given dependency
     *
     * @param clazz      - dependency class
     * @param qualifier  - bean canonicalName / optional
     * @param parameters - dependency parameters / optional
     */
    public static <T> T get(
            Class clazz,
            Qualifier qualifier,
            ParametersDefinition parameters
    ) {
        try {
            return (T) getKoin()
                    .get(clazz, qualifier, parameters);
        } catch (DefinitionParameterException e) {
            e.printStackTrace();
        } catch (NoBeanDefFoundException e) {
            e.printStackTrace();
        } catch (ClosedScopeException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T get(
            Class clazz,
            Qualifier qualifier
    ) {
        return get(clazz, qualifier, null);
    }

    public static <P, S> S bind(
            Class<P> primary,
            Class<S> secondary,
            ParametersDefinition parameters
    ) {
        try {
            return getKoin()
                    .bind(secondary, primary, parameters);
        } catch (NoBeanDefFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <P, S> S bind(
            Class<P> primary,
            Class<S> secondary
    ) {
        return (S) bind(secondary, primary, null);
    }

    public static Koin getKoin() {
        return KoinPlatformTools
                .INSTANCE()
                .defaultContext()
                .get();
    }
}
